package com.sheep.dingding.service;

import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.*;
import com.dingtalk.api.response.*;
import com.sheep.dingding.model.KVModel;
import com.sheep.dingding.model.WorkRecordModel;
import com.taobao.api.ApiException;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;


/**
 * @author wangze
 * @date 2020-09-21 15:04.
 **/
@Service(value = "ddService")
public class DingDingService {

	/**
	 * 调整到1小时50分钟
	 */
	public static final long cacheTime = 1000 * 60 * 55 * 2;
	private final Map<String, KVModel<String>> CACHE = new ConcurrentHashMap<>();

	private final String ACCESS_TOKEN_KEY = "access_token";

	private final String JS_TICKET_KEY = "js_ticket_key";

	private final static String APP_KEY = "dinggsdlnkvjpackomsa";

	private final static String APP_SECRET = "0d_JKS5ND6V0DALPf2mENtuweI01aIZl4cjp5P_Bo0bYdLyxX1HXg0n2AHwHoLt8";


	private final  static String CORP_ID="ding9b5c6970c8c1f3f035c2f4657eb6378f";

	private final  static String AGENT_ID="952102869";

	public String getAccessToken() throws ApiException {
		if (!CACHE.containsKey(ACCESS_TOKEN_KEY) || System.currentTimeMillis() - CACHE.get(ACCESS_TOKEN_KEY).createTime.getTime() > cacheTime) {
			DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
			OapiGettokenRequest request = new OapiGettokenRequest();
			request.setAppkey(APP_KEY);
			request.setAppsecret(APP_SECRET);
			request.setHttpMethod("GET");
			OapiGettokenResponse response = client.execute(request);
			if (!response.isSuccess()) {
				throw new ApiException(response.getErrmsg());
			}
			String accessToken=response.getAccessToken();
			CACHE.put(ACCESS_TOKEN_KEY,new KVModel<>(accessToken,new Date()));
			return accessToken;
		}
		return CACHE.get(ACCESS_TOKEN_KEY).value;

	}

	/**
	 * 当jsapi_ticket未过期时，
	 * 再次调用get_jsapi_ticket
	 * 会获取到一个全新的jsapi_ticket（和旧的jsapi_ticket值不同），
	 * 这个全新的jsapi_ticket的过期时间是2小时。
	 * <p>
	 * jsapi_ticket是一个appKey对应一个，
	 * 所以在使用的时候需要将jsapi_ticket
	 * 以appKey为维度进行缓存下来
	 * （设置缓存过期时间2小时），并不需要每次都通过接口拉取。
	 *
	 * @return
	 * @throws ApiException
	 */
	public String getJsapiTicket(String accessToken) throws ApiException {
		if (!CACHE.containsKey(JS_TICKET_KEY) || System.currentTimeMillis() - CACHE.get(JS_TICKET_KEY).createTime.getTime() > cacheTime){
			DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/get_jsapi_ticket");
			OapiGetJsapiTicketRequest req = new OapiGetJsapiTicketRequest();
			req.setTopHttpMethod("GET");
			OapiGetJsapiTicketResponse execute = client.execute(req, accessToken);
			if (!execute.isSuccess()) {
				throw new ApiException(execute.getErrmsg());
			}
			String ticket=execute.getTicket();
			CACHE.put(JS_TICKET_KEY,new KVModel<>(ticket,new Date()));
			return ticket;
		}
		return CACHE.get(JS_TICKET_KEY).value;
	}
//	public String getJsapiTicket(String accessToken) throws ApiException {
//		DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/get_jsapi_ticket");
//		OapiGetJsapiTicketRequest req = new OapiGetJsapiTicketRequest();
//		req.setTopHttpMethod("GET");
//		OapiGetJsapiTicketResponse execute = client.execute(req, accessToken);
//		if (!execute.isSuccess()) {
//			throw new ApiException(execute.getErrmsg());
//		}
//		String ticket=execute.getTicket();
//		return ticket;
//	}

	public Map<String,Object> getConfig(String url) throws ApiException {
		System.out.println(url);
		String accessToken=this.getAccessToken();
		String ticket=this.getJsapiTicket(accessToken);
		System.out.println("accessToken:"+accessToken);
		System.out.println("ticket:"+ticket);
		// 随机字符串,可以随便填写
		String nonceStr="abcdefghhh";
		long timeStamp = System.currentTimeMillis() / 1000;
		String signature=sign(ticket,nonceStr,timeStamp,url);
		Map<String, Object> configValue = new HashMap<>();
		configValue.put("jsticket", ticket);
		configValue.put("signature", signature);
		configValue.put("nonceStr", nonceStr);
		configValue.put("timeStamp", timeStamp);
		configValue.put("corpId", CORP_ID);
		configValue.put("agentId", AGENT_ID);
		return  configValue;
	}

	public static String sign(String ticket, String nonceStr, long timeStamp, String url) throws ApiException {
		String plain = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "&timestamp=" + String.valueOf(timeStamp)
				+ "&url=" + url;
		try {
			MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
			sha1.reset();
			sha1.update(plain.getBytes("UTF-8"));
			// 字节数组转化成十六进制字符串
			return byteToHex(sha1.digest());
		} catch (NoSuchAlgorithmException e) {
			throw new ApiException(e.getMessage());
		} catch (UnsupportedEncodingException e) {
			throw new ApiException(e.getMessage());
		}
	}
	// 字节数组转化成十六进制字符串
	private static String byteToHex(final byte[] hash) {
		Formatter formatter = new Formatter();
		for (byte b : hash) {
			formatter.format("%02x", b);
		}
		String result = formatter.toString();
		formatter.close();
		return result;
	}


	public String getDingDingUserId(String requestAuthCode, String accessToken) throws ApiException {
		DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/getuserinfo");
		OapiUserGetuserinfoRequest request = new OapiUserGetuserinfoRequest();
		request.setCode(requestAuthCode);
		request.setHttpMethod("GET");
		OapiUserGetuserinfoResponse response = client.execute(request, accessToken);
		if(response.isSuccess()){
			return response.getUserid();
		}
		throw new ApiException(response.getErrmsg());
	}

	/**
	 * 获取当前钉钉登录用户的用户手机号码
	 *
	 * @param requestAuthCode
	 * @return
	 * @throws ApiException
	 */
	public String getUserMobile(String requestAuthCode) throws ApiException {
		String accessToken = this.getAccessToken();
		String userId = this.getDingDingUserId(requestAuthCode, accessToken);
		DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/get");
		OapiUserGetRequest request = new OapiUserGetRequest();
		request.setUserid(userId);
		request.setHttpMethod("GET");
		OapiUserGetResponse response = client.execute(request, accessToken);
		if(response.isSuccess()){
			return response.getMobile();
		}
		throw new ApiException(response.getErrmsg());

	}

	/**
	 * 根据手机号，获取userid
	 * @param mobile
	 * @param access_token
	 * @return
	 * @throws ApiException
	 */
	public  String getUserIdByMobile(String mobile,String access_token) throws ApiException {
		DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/get_by_mobile");
		OapiUserGetByMobileRequest request = new OapiUserGetByMobileRequest();
		request.setMobile(mobile);

		OapiUserGetByMobileResponse execute = client.execute(request, access_token);
		if(execute.isSuccess()){
			return  execute.getUserid();
		}
		throw new ApiException(execute.getErrmsg());
	}

	public String addWorkrecordAddRequest(String userId,WorkRecordModel recordModel,String accessToken) throws ApiException {
		DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/workrecord/add");
		OapiWorkrecordAddRequest req = new OapiWorkrecordAddRequest();
		req.setUserid(userId);
		req.setCreateTime(System.currentTimeMillis());
		req.setTitle(recordModel.getTitle());
		req.setUrl(recordModel.getUrl());
		if(!StringUtils.isEmpty(recordModel.getSourceName())){
			req.setSourceName(recordModel.getSourceName());
		}
		if(!StringUtils.isEmpty(recordModel.getBizId())){
			req.setBizId(recordModel.getBizId());
		}
		req.setFormItemList(recordModel.getFormItemList());
		OapiWorkrecordAddResponse rsp = client.execute(req, accessToken);
		if(rsp.isSuccess()){
			return  rsp.getMsg();
		}
		return  rsp.getErrmsg();
	}

	public String sendToDoMsg(String mobile, String accessToken,String content) throws ApiException {
		String userId=this.getUserIdByMobile(mobile,accessToken);
		DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2");

		OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
		request.setUseridList(userId);
		request.setAgentId(Long.valueOf(AGENT_ID));
		request.setToAllUser(false);

		OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
		msg.setMsgtype("text");
		msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text());
		msg.getText().setContent(content);
		request.setMsg(msg);
		OapiMessageCorpconversationAsyncsendV2Response response = client.execute(request,accessToken);
		if(response.isSuccess()){
			return  response.getMsg();
		}
		throw new ApiException(response.getErrmsg());
	}


	public String sendWorkMsg(String userId,String accessToken) throws ApiException {
		DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2");

		OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
		request.setUseridList(userId);
		request.setAgentId(Long.valueOf(AGENT_ID));
		request.setToAllUser(false);
		OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
		msg.setMsgtype("link");
		msg.setLink(new OapiMessageCorpconversationAsyncsendV2Request.Link());
		msg.getLink().setTitle("test3ababa");
		msg.getLink().setText("test5sdf");
		msg.getLink().setMessageUrl("http://www.baidu.com");
		msg.getLink().setPicUrl("http://www.baidu.com");
		request.setMsg(msg);
		OapiMessageCorpconversationAsyncsendV2Response response = client.execute(request,accessToken);
		if(response.isSuccess()){
			return  response.getMsg();
		}
		return response.getErrmsg();
	}
}
